// Pointers (指针) 示例
// 演示 Pascal 中指针的用法
program p_15_pointers;

{$mode objfpc}{$H+}
// {$mode objfpc} 启用 Object Pascal 模式
// {$H+} 启用长字符串支持（AnsiString）

// 引入单元文件
uses
  SysUtils;  // 系统工具单元，包含常用的系统函数

// 定义指针类型
type
  PInteger = ^Integer;     // 指向整数的指针
  PReal = ^Real;           // 指向实数的指针
  PString = ^String;       // 指向字符串的指针

// 1. 通过指针修改变量值的过程
procedure ModifyValueByPointer(p: PInteger);
begin
  p^ := p^ * 2;  // 通过指针修改值
end;

// 2. 交换两个整数值的过程（使用指针引用）
procedure SwapByPointer(var p1, p2: PInteger);
var
  temp: PInteger;
begin
  temp := p1;
  p1 := p2;
  p2 := temp;
end;

// 所有变量声明移到这里
var
  number: Integer;
  pNumber: PInteger;
  value: Integer;
  data: Integer;
  ptr1: PInteger;
  ptr2: PInteger;
  numbers: array[0..4] of Integer;
  ptrArray: array[0..4] of PInteger;
  i: Integer;
  text: String;
  pText: PString;
  nullPtr: PInteger;

// 程序主入口
begin
  WriteLn('=== Pascal 指针示例 ===');
  WriteLn;
  
  // 1. 基本指针使用
  WriteLn('1. 基本指针使用:');
  number := 42;
  pNumber := @number;
  
  WriteLn('  变量 number 的值: ', number);
  WriteLn('  变量 number 的地址: ', PtrUInt(pNumber));  // 使用 PtrUInt 转换指针为整数显示
  WriteLn('  通过指针访问的值: ', pNumber^);
  
  // 通过指针修改值
  pNumber^ := 100;
  WriteLn('  通过指针修改后的值: ', number);
  
  WriteLn;
  
  // 2. 指针与过程的结合使用
  WriteLn('2. 指针与过程的结合使用:');
  value := 21;
  WriteLn('  修改前 value 的值: ', value);
  
  ModifyValueByPointer(@value);
  WriteLn('  通过指针过程修改后的值: ', value);
  
  WriteLn;
  
  // 3. 多个指针指向同一变量
  WriteLn('3. 多个指针指向同一变量:');
  data := 123;
  ptr1 := @data;
  ptr2 := @data;
  
  WriteLn('  data 的值: ', data);
  WriteLn('  ptr1 指向的值: ', ptr1^);
  WriteLn('  ptr2 指向的值: ', ptr2^);
  
  ptr1^ := 456;
  WriteLn('  通过 ptr1 修改后 data 的值: ', data);
  WriteLn('  ptr2 指向的值: ', ptr2^);
  
  WriteLn;
  
  // 4. 指针数组
  WriteLn('4. 指针数组:');
  numbers[0] := 10;
  numbers[1] := 20;
  numbers[2] := 30;
  numbers[3] := 40;
  numbers[4] := 50;
  
  // 为每个数组元素创建指针
  for i := 0 to 4 do
    ptrArray[i] := @numbers[i];
  
  Write('  原始数组: ');
  for i := 0 to 4 do
    Write(numbers[i], ' ');
  WriteLn;
  
  // 通过指针数组修改值
  for i := 0 to 4 do
    ptrArray[i]^ := ptrArray[i]^ * 2;
  
  Write('  修改后数组: ');
  for i := 0 to 4 do
    Write(numbers[i], ' ');
  WriteLn;
  
  WriteLn;
  
  // 5. 字符串指针
  WriteLn('5. 字符串指针:');
  text := 'Hello Pascal';
  pText := @text;
  
  WriteLn('  原始字符串: ', text);
  pText^ := 'Hello Pointers';  // 通过指针修改字符串
  WriteLn('  通过指针修改后的字符串: ', text);
  
  WriteLn;
  
  // 6. 空指针检查
  WriteLn('6. 空指针检查:');
  nullPtr := Nil;
  
  if nullPtr = Nil then
    WriteLn('  指针为空')
  else
    WriteLn('  指针不为空');
  
  // 安全地使用指针前进行检查
  if nullPtr <> Nil then
    WriteLn('  nullPtr^ = ', nullPtr^)
  else
    WriteLn('  不能解引用空指针');
  
  WriteLn;
  WriteLn('演示了 Pascal 中指针的用法');
  
  // 等待用户按键，防止程序窗口立即关闭
  ReadLn;
end.